#ifndef __EPOLLER__
#define __EPOLLER__
#include <sys/epoll.h>
#include <string.h>
#include <exception>
#include "log.hpp"
#include "NoCopy.hpp"
extern Log log;

class Epoller : public NoCopy
{
public:
    Epoller()
    {
        _epFd = epoll_create(1);
        if(_epFd < 0) {
            log(ERROR, "Epoll create error! why: ", strerror(errno));
            throw std::runtime_error("Epoll create failed");
        } else {
            // throw std::logic_error("I feel awesome!\nJust test!");
            log(INFO, "Epoll create success, _epFd: %d.\n", _epFd);
        }
    }

    ~Epoller()
    {
        if(_epFd >= 0) {
            log(INFO, "~Epoller(), close _epFd now.\n");
            close(_epFd);
        }
    }

    void epollerCtl(int op, int fd, uint32_t event)
    {
        if(op == EPOLL_CTL_DEL) {
            // 对该文件描述符指向的节点进行删除
            int n = epoll_ctl(_epFd, op, fd, nullptr);
            if(n < 0) {
                log(ERROR, "Epoll delete control error! why: ", strerror(errno));
                throw std::runtime_error("Epoll delete control failed");
            } 
        } else {
            // 添加或者修改
            struct epoll_event ee;
            ee.events = event;
            ee.data.fd = fd;            // 添加data字段的fd，目的是方便后期我们得知是哪一个fd就绪了。在handlerEvent中会永奥
            int n = epoll_ctl(_epFd, op, fd, &ee);
            if(n < 0) {
                log(ERROR, "Epoll control error! why: ", strerror(errno));
                throw std::runtime_error("Epoll control failed");
            } 
        }
    }

    int epollerWait(struct epoll_event *events, int maxevents)
    {
        return epoll_wait(_epFd, events, maxevents, _timeOut);
    }
private:
    int _epFd;
    int _timeOut = -1;
};
#endif